package com.bhatni.taskmanager;

import com.bhatni.taskmanager.schedule.Schedule;
import com.bhatni.taskmanager.task.Task;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * 
 * @author virendra
 */
public class TaskManager {

    TaskList tasklist = new TaskList();
    static final SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    public void addTask(Task task) {
        this.tasklist.addTask(task);
        scheduleTask(task);
    }

    void scheduleTask(Task task) {
        Date schedule = task.getSchedule().getNextSchedule();
        this.tasklist.addScheduleTask(task, schedule);
    }

    public void RunTasks() {
        LinkedList pendingtasks = new LinkedList();
        while (this.tasklist.hasScheduledTasks()) {
            pendingtasks.clear();

            this.tasklist.getPendingTasks(pendingtasks);

            while (!pendingtasks.isEmpty()) {
                Task task = (Task) pendingtasks.removeFirst();
                System.out.println(dateformat.format(Calendar.getInstance().getTime()) + ": Running task " + task.getName());
                task.run();

                scheduleTask(task);
            }

            Date nextSchedule = this.tasklist.getNextSchedule();

            long currenttime = System.currentTimeMillis();
            if ((nextSchedule != null) && (nextSchedule.getTime() - currenttime > 0L)) {
                try {
                    Thread.sleep(nextSchedule.getTime() - currenttime);
                } catch (InterruptedException localInterruptedException) {
                }
            }
        }
    }

    public void loadTasksFromXML(String XMLFilePath) {
        Document doc;
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            doc = builder.parse(XMLFilePath);
        } catch (Exception e) {
            System.out.println("Error: Unable to load " + XMLFilePath + ". "
                    + e.getMessage());
            return;
        }

        XMLBeanUtils xmlBeanUtils = new XMLBeanUtils();

        NodeList tasks = xmlBeanUtils.getChildrenbyTagName(doc.getDocumentElement(), "Task");
        for (int i = 0; i < tasks.getLength(); i++) {
            Element eleTask = (Element) tasks.item(i);
            Task task = (Task) xmlBeanUtils.createInstance(eleTask, getClass().getPackage().getName(), "Task");
            if (task.getName() == null) {
                task.setName("Task" + Integer.toString(i+1));
            }
            NodeList schedules = xmlBeanUtils.getChildrenbyTagName(eleTask, "Schedule");
            Element eleSchedule = (Element) schedules.item(0);
            Schedule schedule = (Schedule) xmlBeanUtils.createInstance(eleSchedule, getClass().getPackage().getName(), "Schedule");
            task.setSchedule(schedule);

            addTask(task);
        }
    }

    public static void main(String[] args) {
        if (args.length < 1) {
            help();
            return;
        }

        TaskManager tm = new TaskManager();
        tm.loadTasksFromXML(args[0]);
        tm.RunTasks();

        System.out.println("Done");
    }

    static void help() {
        System.out.println("Syntax: TaskManager <XML config file>");
    }
}
